﻿using System;
using System.Configuration;
using System.Data.Services.Client;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Smarly.Core;
using log4net.Appender;
using log4net.Core;

namespace Smarly.Logs
{
	public class AzureTableStorageAppender : AppenderSkeleton
	{
		public string TableStorageConnectionStringName { get; set; }
		private LogServiceContext _ctx;
		private string _tableEndpoint;
		public override void ActivateOptions()
		{
			base.ActivateOptions();
			CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureStorageConnectionString"].ConnectionString);
			_tableEndpoint = storageAccount.TableEndpoint.AbsoluteUri;

			CloudTableClient client = new CloudTableClient(storageAccount.TableEndpoint, storageAccount.Credentials);
			_ctx = new LogServiceContext(client);
		}

		protected override void Append(LoggingEvent loggingEvent)
		{
			Action doWriteToLog = () =>
				                      {
					                      try
					                      {
						                      var exceptionObject = loggingEvent.ExceptionObject;

																	AspNetException aspEx = null;

						                      if (exceptionObject is AspNetException)
						                      {
							                      aspEx = (AspNetException) exceptionObject;
							                      exceptionObject = ((AspNetException) exceptionObject).Ex;
						                      }

						                      var logEntry = new LogEntry
							                                     {
								                                     Timestamp = loggingEvent.TimeStamp,
								                                     Message = loggingEvent.RenderedMessage,
								                                     Level = loggingEvent.Level.Name,
								                                     LoggerName = loggingEvent.LoggerName,
								                                     Domain = loggingEvent.Domain,
								                                     ThreadName = loggingEvent.ThreadName,
								                                     Identity = loggingEvent.Identity,
																										 CreateDate = DateTime.UtcNow.ToString("dd-MM-yy HH:mm:ss"),
								                                     Exception =
									                                     exceptionObject == null
										                                     ? null
										                                     : exceptionObject.ToString()
							                                     };

						                      var unknownPageEx = exceptionObject as UnknownPageException;
																	if (unknownPageEx != null)
																		unknownPageEx.Populate(logEntry);
																	else if (aspEx != null)
																		aspEx.Populate(logEntry);

						                      _ctx.Log(logEntry);
					                      }
					                      catch (DataServiceRequestException e)
					                      {
						                      ErrorHandler.Error(string.Format("{0}: Could not write log entry to {1}: {2}",
						                                                       GetType().AssemblyQualifiedName, _tableEndpoint, e.Message));
					                      }
				                      };
			doWriteToLog.BeginInvoke(null, null);
		}
	}
}